/*
 * Copyright (C) 2009 Rob Cash
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * StateMachine.java
 * 
 * Created on Jan 1, 2009 at 12:03:46 PM
 */

package org.robcash.commons.util;

import java.util.Set;

/**
 * State machine description
 * @param <T> Type of value contained by machine state
 * @author Rob
 */
public interface StateMachine<T> extends Iterable<State<T>> {

    /**
     * Add a state to the state machine
     * @param state State to add
     * @return true if the state was added; false if it was not added due to
     * having previously been added
     */
    public boolean addState(State<T> state);

    /**
     * Add a state to the state machine
     * @param state State to add
     * @param initialState Indicates if this is the initial state
     * @return true if the state was added; false if it was not added due to
     * having previously been added
     */
    public boolean addState(State<T> state, boolean initialState);

    /**
     * Add a transition from one state to another
     * @param transition State to state transition
     */
    public void addTransition(StateTransition<T> transition);

    /**
     * Remove a state
     * @param state State to remove
     * @exception IllegalStateException Thrown if the state being removed is the current state
     */
    public void removeState(State<T> state) throws IllegalStateException;

    /**
     * Remove a transition from one state to another
     * @param transition State to state transition
     */
    public void removeTransition(StateTransition<T> transition);

    /**
     * Get the current state
     * @return current state
     */
    public State<T> getCurrentState();

    /**
     * Get the transitions available for the specified state
     * @param state State whose transitions should be returned
     * @return Transitions for the specified state
     */
    public Set<StateTransition<T>> getTransitionsForState(State<T> state);

    /**
     * Indicates if the current state has a transition of the specified name
     * @param transitionName Name of transition to check
     * @return <tt>true</tt> if the current state has a transition named
     * <tt>name</tt>
     */
    public boolean canTransitionTo(String transitionName);

    /**
     * Transition to a new state given the name of a transition
     * @param transition Transition to follow
     * @return New state
     * @throws IllegalStateException Thrown if the specified transition is not
     * valid for the current state
     */
    public State<T> transitionToNewState(StateTransition<T> transition) throws IllegalStateException;

    /**
     * Transition to a new state given the name of a transition
     * @param transitionName Name of transition to follow
     * @return New state
     * @throws IllegalStateException Thrown if the specified transition name is
     * not valid for the current state
     */
    public State<T> transitionToNewState(String transitionName) throws IllegalStateException;

    /**
     * Indicates that the current state is terminal. A state is terminal if it
     * has no transitions.
     * @return <tt>true</tt> if the current state has no transitions
     */
    public boolean isFinished();

    /**
     * Reset the state machine to the initial state
     */
    public void reset();

}
